package old_api

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"onvif_server/api/camera"
	"onvif_server/internal/handler"
	"onvif_server/internal/model"
	"onvif_server/internal/service"
	"onvif_server/internal/utils"
	"time"
)

type OldApiHandler struct {
	*handler.Handler
	cameraService service.CameraService
	loc           *time.Location
}

func NewOldApiHandler(handler *handler.Handler, cameraService service.CameraService, loc *time.Location) *OldApiHandler {
	return &OldApiHandler{
		Handler:       handler,
		cameraService: cameraService,
		loc:           loc,
	}
}

func (h *OldApiHandler) Register(engine *gin.Engine) {

	engine.GET("/device", auth, h.device)                      //完成
	engine.GET("/api/onehourvideo", auth, h.getHourM3u8)       //完成
	engine.GET("/api/onedayvideo", auth, h.getDayM3u8)         //完成
	engine.GET("/getSnapshorturl", auth, h.getSnapUrl)         //完成
	engine.POST("/getAlarmVideoUrl", auth, h.getAlarmVideoUrl) //完成
	engine.GET("/api/getHistory", auth, h.getHistory)          //完成
	engine.GET("/api/videosearch", auth, h.videoSearch)        //完成
	engine.GET("/api/time", auth, h.getTime)                   //已完成
}

func (h *OldApiHandler) getTime(ctx *gin.Context) {
	req := CamidReq{}
	if err := ctx.ShouldBind(&req); err != nil {
		ctx.JSON(400, gin.H{"message": err.Error()})
		return
	}
	dt, err := h.cameraService.GetDatetime(ctx, &camera.IdOrDeviceIdReq{DeviceId: req.Camid})
	if err != nil {
		ctx.JSON(400, gin.H{"message": err.Error()})
		return
	}
	ctx.JSON(200, gin.H{"datetime": dt.Format(utils.FormatDatetime)})
}

func (h *OldApiHandler) device(ctx *gin.Context) {
	deviceId := ctx.Query("deviceid")
	if deviceId != "" {
		_camera, err := h.cameraService.Detail(ctx, &camera.IdOrDeviceIdReq{DeviceId: deviceId})
		if err != nil {
			ctx.JSONP(400, gin.H{
				"retcode": -1,
				"message": err.Error(),
			})
			return
		}
		ctx.JSONP(200, gin.H{
			"retcode": 0,
			"data":    modelToRet(_camera),
		})
		return
	} else {
		req := camera.ListReq{}
		req.Infinite()
		_, list, err := h.cameraService.List(ctx, &req)
		if err != nil {
			ctx.JSONP(400, gin.H{
				"retcode": -1,
				"message": err.Error(),
			})
			return
		}

		ret := make([]map[string]any, len(list))
		for i := range list {
			ret[i] = modelToRet(list[i])
		}
		ctx.JSONP(200, gin.H{
			"retcode": 0,
			"data":    ret,
		})
	}
}

func (h *OldApiHandler) videoSearch(ctx *gin.Context) {
	req := VideoSearchReq{}
	if err := ctx.ShouldBind(&req); err != nil {
		ctx.JSON(400, gin.H{"message": err.Error()})
		return
	}
	res, err := h.cameraService.SearchVideo(ctx, &camera.VideoSearchReq{DeviceId: req.Camid, StartTime: req.Begin, EndTime: req.End})
	if err != nil {
		ctx.JSON(400, gin.H{"message": err.Error()})
		return
	}
	ctx.JSON(200, gin.H{"data": res})
}

func (h *OldApiHandler) getHistory(ctx *gin.Context) {
	req := CamidReq{}
	if err := ctx.ShouldBind(&req); err != nil {
		ctx.JSON(400, gin.H{"message": err.Error()})
		return
	}
	res, err := h.cameraService.GetHistory(ctx, &camera.GetHistoryReq{DeviceId: req.Camid})
	if err != nil {
		ctx.JSON(400, gin.H{"message": err.Error()})
		return
	}
	ctx.JSON(200, gin.H{"data": res.Data, "filelist": res.FileList, "filelistNew": res.FileListNew})
}

func (h *OldApiHandler) getAlarmVideoUrl(ctx *gin.Context) {
	req := ImgReq{}
	if err := ctx.ShouldBind(&req); err != nil {
		ctx.JSON(400, gin.H{
			"code": -1,
			"msg":  err.Error(),
		})
		return
	}
	res, err := h.cameraService.GetMp4ByImg(ctx, &camera.GetMp4ByImgReq{Img: req.Img})
	if err != nil {
		ctx.JSON(400, gin.H{
			"code": -1,
			"msg":  err.Error(),
		})
		return
	}
	ctx.JSON(200, gin.H{
		"code": 0,
		"url":  res,
	})
}

func (h *OldApiHandler) getSnapUrl(ctx *gin.Context) {
	req := CameraConnReq{}
	if err := ctx.ShouldBind(&req); err != nil {
		ctx.JSONP(400, gin.H{
			"retcode": -1,
			"message": err.Error(),
		})
		return
	}
	res, err := h.cameraService.GetSnapUrl(ctx, &camera.GetSnapUrlReq{
		DeviceId: req.Camid,
		Addx:     req.Addx,
		Username: req.Username,
		Password: req.Password,
	})
	if err != nil {
		ctx.JSONP(400, gin.H{
			"retcode": -1,
			"message": err.Error(),
		})
		return
	}
	ctx.JSONP(200, gin.H{
		"retcode": 0,
		"url":     res,
	})
}

func (h *OldApiHandler) getDayM3u8(ctx *gin.Context) {
	req := DateReq{}
	if err := ctx.ShouldBind(&req); err != nil {
		ctx.JSONP(400, gin.H{
			"retcode": -1,
			"message": err.Error(),
		})
		return
	}
	newReq := &camera.GetM3u8Req{
		DeviceId: req.Camid,
	}

	_nt, err := time.ParseInLocation("2006-01-02", req.Date, h.loc)
	if err != nil {
		ctx.JSONP(400, gin.H{
			"retcode": -1,
			"message": "time 参数错误 YYYY-mm-DD-H",
		})
		return
	}
	newReq.Time = _nt.Unix()
	res, err := h.cameraService.GetM3u8(ctx, newReq, "day")
	if err != nil {
		ctx.JSONP(400, gin.H{
			"retcode": -1,
			"message": err.Error(),
		})
		return
	}
	ctx.JSONP(200, gin.H{
		"retcode": 0,
		"data":    res,
	})
}

func (h *OldApiHandler) getHourM3u8(ctx *gin.Context) {
	req := TimeReq{}
	if err := ctx.ShouldBind(&req); err != nil {
		ctx.JSONP(400, gin.H{
			"retcode": -1,
			"message": err.Error(),
		})
		return
	}
	newReq := &camera.GetM3u8Req{
		DeviceId: req.Camid,
	}

	_nt, err := time.ParseInLocation("2006-01-02-15", req.Time, h.loc)
	if err != nil {
		ctx.JSONP(400, gin.H{
			"retcode": -1,
			"message": "time 参数错误 YYYY-mm-DD-H",
		})
		return
	}
	newReq.Time = _nt.Unix()
	res, err := h.cameraService.GetM3u8(ctx, newReq, "hour")
	if err != nil {
		ctx.JSONP(400, gin.H{
			"retcode": -1,
			"message": err.Error(),
		})
		return
	}
	ctx.JSONP(200, gin.H{
		"retcode": 0,
		"data":    res[0],
	})
}

func auth(ctx *gin.Context) {
	// 如果本地请求则不检查认证信息
	if ctx.ClientIP() != "127.0.0.1" {
		authHeader := ctx.Request.Header.Get("token")
		if authHeader != "xwc" {
			ctx.JSON(400, gin.H{
				"retcode": -1,
				"msg":     "Request header has no auth",
			})
			ctx.Abort()
		}
	}
}

func modelToRet(camera *model.Camera) map[string]any {
	lng := ""
	lat := ""
	if camera.Point.Lng > 0 {
		lng = fmt.Sprintf("%f", camera.Point.Lng)
	}
	if camera.Point.Lat > 0 {
		lat = fmt.Sprintf("%f", camera.Point.Lat)
	}
	return map[string]any{
		"id":         camera.ID,
		"deviceid":   camera.DeviceId,
		"Alias":      camera.Alias,
		"online":     camera.Online,
		"username":   camera.Username,
		"password":   camera.Password,
		"record":     camera.Record,
		"rtspuri":    camera.RtspUri,
		"rtspuri1":   camera.RtspUri1,
		"rtspuri2":   camera.RtspUri2,
		"filepath":   camera.Filepath,
		"addx":       camera.Addx,
		"createtime": camera.CreatedAt,
		"key":        camera.Key,
		"uuid":       camera.UUID,
		"lon":        lng,
		"lat":        lat,
		"build":      camera.Build,
		"storey":     camera.Storey,
		"location":   camera.Location,
		"barnd":      camera.Brand,
		"model":      camera.Model,
		"height":     camera.Height,
		"Width":      camera.Width,
		"snapurl":    camera.SnapUrl,
	}
}
